﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Collections.Concurrent;

using WorkStation.Frameworks.Core;
using WorkStation.Frameworks.Core.Extensions;

using Microsoft.Practices.ServiceLocation;

namespace WorkStation.Frameworks.EasyBus
{
    /// <summary>
    /// 总线服务容器
    /// </summary>
    public class ServiceContainer
    {
        protected ConcurrentDictionary<Type, Tuple<Func<object>, Func<object>>> _cache = new ConcurrentDictionary<Type, Tuple<Func<object>, Func<object>>>();
        protected ConcurrentDictionary<Type, Tuple<Func<object>, Func<object>>> _collectionCache = new ConcurrentDictionary<Type, Tuple<Func<object>, Func<object>>>();

        protected static ServiceContainer _INSTANCE = null;
        protected static Func<ServiceContainer> _CREATOR = () => new ServiceContainer();

        protected ServiceContainer() 
        {
            
        }

        public static ServiceContainer Current 
        {
            get 
            {
                Interlocked.CompareExchange<ServiceContainer>(ref _INSTANCE, _CREATOR.Invoke(), null);

                return _INSTANCE;
            }
        }
        
        /// <summary>
        /// 注册单个服务
        /// </summary>
        /// <typeparam name="TService">服务类型</typeparam>
        /// <param name="creator">服务获取委托</param>
        /// <param name="defaultImpl">默认实现委托</param>
        /// <returns></returns>
        public ServiceContainer Register<TService>(Func<TService> creator, Func<TService> defaultImpl = null) where TService : class
        {
            this._cache[typeof(TService)] = new Tuple<Func<object>, Func<object>>(creator, defaultImpl);

            return this;
        }

        /// <summary>
        /// 注册一组服务
        /// </summary>
        /// <typeparam name="TService">服务类型</typeparam>
        /// <param name="creator">服务获取委托</param>
        /// <param name="defaultImpl">默认实现委托</param>
        /// <returns></returns>
        public ServiceContainer RegisterCollection<TService>(Func<IEnumerable<TService>> creator, Func<IEnumerable<TService>> defaultImpl = null) where TService : class
        {
            this._collectionCache[typeof(TService)] = new Tuple<Func<object>, Func<object>>(creator, defaultImpl);

            return this;
        }

        /// <summary>
        /// 获取单个服务
        /// </summary>
        /// <typeparam name="TService">服务类型</typeparam>
        /// <returns></returns>
        public TService GetInstance<TService>() where TService : class
        {
            Type key = typeof(TService);

            if (!this._cache.ContainsKey(key)) 
            {
                throw new EasyBusException("没有在ServiceContainer设置【{0}】的实现".Fmt(key.FullName));
            }

            Func<TService> creator = this._cache[key].Item1 as Func<TService>;
            Func<TService> defaultValue = this._cache[key].Item2 as Func<TService>;

            TService res = MethodPipeline.Wrap(creator)
                                         .Error((args, result) => (defaultValue != null).WhenTrue(() => result.Result = defaultValue()))
                                         .Final((args, result) => (result.Result == null).WhenTrue(() => result.Result = (defaultValue != null).WhenTrue(() => defaultValue())))
                                         .Execute()
                                         .Result as TService;
            if (res == null) 
            {
                throw new EasyBusException("【{0}】设置异常，没有取到正确的实现".Fmt(key.FullName));
            }

            return res;
        }

        /// <summary>
        /// 获取一组服务
        /// </summary>
        /// <typeparam name="TService">服务类型</typeparam>
        /// <returns></returns>
        public IEnumerable<TService> GetAllInstances<TService>() where TService : class
        {
            Type key = typeof(TService);

            if (!this._collectionCache.ContainsKey(key))
            {
                throw new EasyBusException("没有在ServiceContainer设置【{0}】的实现".Fmt(key.FullName));
            }

            Func<IEnumerable<TService>> creator = this._collectionCache[key].Item1 as Func<IEnumerable<TService>>;
            Func<IEnumerable<TService>> defaultValue = this._collectionCache[key].Item2 as Func<IEnumerable<TService>>;

            IEnumerable<TService> res =  MethodPipeline.Wrap(creator)
                                                       .Error((args, result) => (defaultValue != null).WhenTrue(() => defaultValue()))
                                                       .Final((args, result) => 
                                                       { 
                                                           (result.Result == null).WhenTrue(() => (defaultValue != null).WhenTrue(() => result.Result = defaultValue())); 
                                                           ((result.Result as IEnumerable<TService>).Count() == 0).WhenTrue(() => result.Result = (defaultValue != null).WhenTrue(() => defaultValue()));
                                                       })
                                                       .Execute()
                                                       .Result as IEnumerable<TService>;
            if (res == null)
            {
                throw new EasyBusException("【{0}】设置异常，没有取到正确的实现".Fmt(key.FullName));
            }

            return res;
        }
    }
}
